package com.syaccp.service.impl;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.annotation.Resource;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.syaccp.exception.CrmebException;
import com.syaccp.mapper.SysRoleMapper;
import com.syaccp.model.SysMenu;
import com.syaccp.model.SysRole;
import com.syaccp.model.SysRoleMenu;
import com.syaccp.request.PageParamRequest;
import com.syaccp.request.SysRoleRequest;
import com.syaccp.request.SysRoleSearchRequest;
import com.syaccp.response.RoleInfoResponse;
import com.syaccp.service.SysMenuService;
import com.syaccp.service.SysRoleMenuService;
import com.syaccp.service.SysRoleService;
import com.syaccp.vo.MenuCheckTree;
import com.syaccp.vo.MenuCheckVo;

import cn.hutool.core.util.ObjectUtil;

/**
 * <p>
 * 角色信息表 服务实现类
 * </p>
 *
 * @author lixin
 * @since 2023-07-02
 */
@Service("sysRoleService")
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

	@Autowired
	private SysRoleMapper sysRoleMapper;

	@Autowired
	private TransactionTemplate transactionTemplate;

	@Resource
	private SysRoleMenuService sysRoleMenuService;

	@Resource
	private SysMenuService sysMenuService;

	@Override
	public List<SysRole> getAllList() {

		LambdaQueryWrapper<SysRole> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(SysRole::getStatus, 0);
		lambdaQueryWrapper.eq(SysRole::getDelFlag, 0);
		lambdaQueryWrapper.orderByAsc(SysRole::getId);
		return sysRoleMapper.selectList(lambdaQueryWrapper);
	}

	@Override
	public List<SysRole> getList(SysRoleSearchRequest request, PageParamRequest pageParamRequest) {
		PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
		LambdaQueryWrapper<SysRole> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		if (ObjectUtil.isNotNull(request.getStatus())) {
			lambdaQueryWrapper.eq(SysRole::getStatus, request.getStatus());
		}
		if (ObjectUtil.isNotNull(request.getRoleName())) {
			lambdaQueryWrapper.like(SysRole::getName, request.getRoleName());
		}
		lambdaQueryWrapper.eq(SysRole::getDelFlag, 0);
		lambdaQueryWrapper.orderByAsc(SysRole::getId);
		return sysRoleMapper.selectList(lambdaQueryWrapper);
	}

	@Override
	public Boolean add(SysRoleRequest sysRoleRequest) {

		if (existName(sysRoleRequest.getName(), null)) {
			throw new CrmebException("角色名称重复");
		}

		//1,2,3,4
		List<Integer> ruleList = Stream.of(sysRoleRequest.getRules()
						.split(",")).map(Integer::valueOf).distinct()
				.collect(Collectors.toList());
		SysRole sysRole = new SysRole();
		BeanUtils.copyProperties(sysRoleRequest, sysRole);
		sysRole.setId(null);
		return transactionTemplate.execute(e -> {
			boolean save = save(sysRole);
			if (!save) {
				return Boolean.FALSE;
			}
			List<SysRoleMenu> roleMenuList = ruleList.stream().map(menuId -> {
				SysRoleMenu sysRoleMenu = new SysRoleMenu();
				sysRoleMenu.setRoleId(sysRole.getId());
				sysRoleMenu.setMenuId(menuId);
				return sysRoleMenu;
			}).collect(Collectors.toList());
			sysRoleMenuService.saveBatch(roleMenuList, 100);
			return Boolean.TRUE;
		});
	}

	@Override
	public Boolean delete(Integer id) {

		SysRole sysRole = getById(id);
		if (ObjectUtil.isNull(sysRole)) {
			throw new CrmebException("角色已删除");
		}
		return transactionTemplate.execute(e -> {
			sysRoleMapper.deleteById(id);
			sysRoleMenuService.deleteByRoleId(id);
			return Boolean.TRUE;
		});
	}

	@Override
	public Boolean edit(SysRoleRequest sysRoleRequest) {

		SysRole role = getById(sysRoleRequest.getId());
        if (ObjectUtil.isNull(role)) {
            throw new CrmebException("角色不存在");
        }
        if (!role.getName().equals(sysRoleRequest.getName())) {
            if (existName(sysRoleRequest.getName(), sysRoleRequest.getId())) {
                throw new CrmebException("角色名称重复");
            }
        }
        SysRole sysRole =new SysRole();
        BeanUtils.copyProperties(sysRoleRequest, sysRole);

        List<Integer> ruleList = Stream.of(sysRoleRequest.getRules().split(",")).map(Integer::valueOf).distinct().collect(Collectors.toList());
        List<SysRoleMenu> roleMenuList = ruleList.stream().map(rule -> {
        	SysRoleMenu roleMenu = new SysRoleMenu();
            roleMenu.setRoleId(sysRole.getId());
            roleMenu.setMenuId(rule);
            return roleMenu;
        }).collect(Collectors.toList());
        return transactionTemplate.execute(e -> {
            updateById(sysRole);
            sysRoleMenuService.deleteByRoleId(sysRole.getId());
            sysRoleMenuService.saveBatch(roleMenuList, 100);
            return Boolean.TRUE;
        });
	}

	@Override
	public RoleInfoResponse getInfo(Integer id) {

		SysRole sysRole = getById(id);
		if (ObjectUtil.isNull(sysRole)) {
			throw new CrmebException("角色不存在");
		}
		// 查询角色对应的菜单(权限)
		List<SysMenu> menuList = sysMenuService.getCacheList();
		List<Integer> menuIdList = sysRoleMenuService.getMenuListByRoleId(id);

		List<MenuCheckVo> menuCheckVoList = menuList.stream().map(menu -> {
			MenuCheckVo menuCheckVo = new MenuCheckVo();
			BeanUtils.copyProperties(menu, menuCheckVo);
			if (menuIdList.contains(menu.getId())) {
				menuCheckVo.setChecked(true);
			} else {
				menuCheckVo.setChecked(false);
			}
			return menuCheckVo;
		}).collect(Collectors.toList());

		RoleInfoResponse response = new RoleInfoResponse();
		BeanUtils.copyProperties(sysRole, response);
		response.setMenuList(new MenuCheckTree(menuCheckVoList).buildTree());
		return response;
	}

	@Override
	public Boolean updateStatus(Integer id, Integer status) {

		SysRole role = getById(id);
		if (ObjectUtil.isNull(role)) {
			throw new CrmebException("角色不存在");
		}
		if (role.getStatus().equals(status)) {
			return true;
		}
		role.setStatus(status);
		return updateById(role);
	}

	/**
	 * 判断角色名称是否存在
	 *
	 * @param roleName 角色名称
	 * @param id       角色id
	 * @return Boolean
	 */
	private Boolean existName(String name, Integer id) {
		LambdaQueryWrapper<SysRole> lqw = Wrappers.lambdaQuery();
		lqw.eq(SysRole::getName, name);
		if (ObjectUtil.isNotNull(id)) {
			lqw.ne(SysRole::getId, id);
		}
		lqw.last(" limit 1");
		Integer count = sysRoleMapper.selectCount(lqw);
		return count > 0;
	}

}
